Skip to content

gh-109532: fix socket HOWTO inaccuracy about send() on broken connection#144747

Open
Gh-Novel wants to merge 2 commits intopython:mainfrom
Gh-Novel:fix-issue-109532
Open

gh-109532: fix socket HOWTO inaccuracy about send() on broken connection#144747
Gh-Novel wants to merge 2 commits intopython:mainfrom
Gh-Novel:fix-issue-109532

Conversation

@Gh-Novel
Copy link

@Gh-Novel Gh-Novel commented Feb 12, 2026

Summary

Corrects an inaccuracy in the Socket Programming HOWTO (Doc/howto/sockets.rst) about send() behavior when the remote end has disconnected.

The existing text stated "if a socket send or recv returns after handling 0 bytes, the connection has been broken." In practice, send() on a broken connection raises OSError (specifically BrokenPipeError/EPIPE) rather than returning 0. Only recv() returns 0 bytes to indicate disconnection.

Changes

  • Fixed the prose to correctly distinguish between send() (raises OSError) and recv() (returns 0 bytes)
    • Added a clarifying comment to the mysend code example

Testing

  • Sphinx doc build passes with zero warnings
    • Verified with a Python test script that send() raises BrokenPipeError and recv() returns b''

📚 Documentation preview 📚: https://cpython-previews--144747.org.readthedocs.build/

…onnection

Correct the claim that send() returns 0 bytes on a broken connection.
In practice, send() on a broken connection raises OSError (EPIPE) rather
than returning 0. Only recv() returns 0 bytes to indicate disconnection.

Add a clarifying comment to the mysend example noting this distinction.
Copy link
Contributor

@bkap123 bkap123 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that these are good (and important) changes. I think that the difference between how send and recv work for a closed connection could be better emphasized (see comment).

that *there is no* :abbr:`EOT (End of Transfer)` *on a socket.* I repeat: if a socket
``send`` or ``recv`` returns after handling 0 bytes, the connection has been
broken. If the connection has *not* been broken, you may wait on a ``recv``
that *there is no* :abbr:`EOT (End of Transfer)` *on a socket.* I repeat: if a
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes look good.
The one suggestion I have is to emphasize that calling send on a closed socket results in an OSError and thus should not actually happen in real code. In contrast, recv returning 0 for a closed socket is a feature. There is a paragraph above that explains what a return value of 0 from recv means, but I think there could be a better explanation of return values/exceptions forsend. Possibly say: In contrast, you should never call send on a broken socket, as it results in an OSError.

that *there is no* :abbr:`EOT (End of Transfer)` *on a socket.* I repeat: if a socket
``send`` or ``recv`` returns after handling 0 bytes, the connection has been
broken. If the connection has *not* been broken, you may wait on a ``recv``
that *there is no* :abbr:`EOT (End of Transfer)` *on a socket.* I repeat: if a
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
that *there is no* :abbr:`EOT (End of Transfer)` *on a socket.* I repeat: if a
that *there is no* :abbr:`EOT (End of Transfer)` *on a socket.* If a

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the review! I've addressed both suggestions - removed "I repeat:" and restructured the paragraph to better emphasize that send() on a broken socket raises OSError (an error you should handle), in contrast to recv() returning 0 bytes as a deliberate disconnect signal.

Remove informal 'I repeat:' phrasing. Restructure paragraph to clearly
contrast recv() returning 0 bytes (a deliberate signal of disconnection)
with send() raising OSError (an error condition — should never be called
on a broken socket).

Co-authored-by: bkap123 <[email protected]>
Copy link
Contributor

@bkap123 bkap123 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left one more suggestion, but otherwise LGTM!
Also as a reminder, if happen to be using an LLM, just remember these rules.

@@ -201,6 +203,8 @@ length message::
sent = self.sock.send(msg[totalsent:])
if sent == 0:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually think that we can get rid of this if clause and the RuntimeError exception since send will already raise an error on a broken connection. That would also make more sense because your comment below is basically saying that send raises an error automatically so there is no reason to check its return value.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting review docs Documentation in the Doc dir skip news

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

2 participants

Comments